package com.example.tool.service.weather;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONObject;
import com.example.tool.bean.business.MojiCityDO;
import com.example.tool.bean.business.TqCityDO;
import com.example.tool.bean.weather.WeatherForecastCityDataDTO;
import com.example.tool.bean.weather.WeatherForecastListDTO;
import com.example.tool.bean.weather.WeatherForecastListExportDTO;
import com.example.tool.bean.weather.WeatherForecastResultDTO;
import com.example.tool.bean.weather.WeatherForecastWeekExportDTO;
import com.example.tool.bean.weather.WeatherHistoryDataListDTO;
import com.example.tool.bean.weather.WeatherHistoryGetResponse;
import com.example.tool.bean.weather.WeatherHistoryQueryTempDTO;
import com.example.tool.bean.weather.WeatherHistoryResultVo;
import com.example.tool.bean.weather.WeatherMojiCommonResponse;
import com.example.tool.conf.ToolConstants;
import com.example.tool.mapper.MojiCityMapper;
import com.example.tool.mapper.TqCityMapper;
import com.example.tool.util.DateUtil;
import com.example.tool.util.WeatherMojiUtil;
import com.example.tool.util.WeatherUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@Slf4j
public class WeatherServiceImpl implements WeatherService {

    @Autowired
    private TqCityMapper tqCityMapper;
    @Autowired
    private MojiCityMapper mojiCityMapper;

    @Override
    public WeatherHistoryResultVo queryHistoryWeather(String cityIds, String year, String month, String startDate, String endDate) {
        if (StringUtils.isBlank(cityIds)) {
            throw new RuntimeException("城市ID不能为空");
        }
        WeatherHistoryResultVo resultVo = new WeatherHistoryResultVo();
        List<WeatherHistoryDataListDTO> resultList = new ArrayList<>();
        String[] cityIdArr = cityIds.split(",");
        for (String cityId : cityIdArr) {
            WeatherHistoryGetResponse weatherHistoryGetResponse = WeatherUtil.queryHistoryWeather(cityId, year, month, startDate, endDate);
            List<WeatherHistoryDataListDTO> list = weatherHistoryGetResponse.getList();
            resultList.addAll(list);
            if (resultVo.getDays() == null) {
                resultVo.setDays(weatherHistoryGetResponse.getDays());
                resultVo.setDateStart(weatherHistoryGetResponse.getDate_start());
                resultVo.setDateEnd(weatherHistoryGetResponse.getDate_end());
            }
        }
        resultVo.setDataList(resultList);
        return resultVo;
    }

    @Override
    public List<WeatherHistoryDataListDTO> queryHistoryWeatherBatch(List<WeatherHistoryQueryTempDTO> queryList) {
        List<TqCityDO> tqCityDOList = tqCityMapper.getAllChinaCity();
        Map<String, TqCityDO> cityMap = tqCityDOList.stream().collect(Collectors.toMap(TqCityDO::getCityZh, Function.identity()));
        List<WeatherHistoryDataListDTO> resultList = new ArrayList<>();
        for (WeatherHistoryQueryTempDTO queryDTO : queryList) {
            String cityName = queryDTO.getCityName();
            TqCityDO tqCityDO = cityMap.get(cityName);
            if (tqCityDO == null) {
                log.info("Tq城市不存在：{}", cityName);
                continue;
            }
            String year = queryDTO.getYear();
            String month = queryDTO.getMonth();
            String startDate = queryDTO.getStartDate();
            String endDate = queryDTO.getEndDate();
            String cityId = tqCityDO.getId().replace("CN", "");
            try {
                WeatherHistoryGetResponse weatherHistoryGetResponse = WeatherUtil.queryHistoryWeather(cityId, year, month, startDate, endDate);
                List<WeatherHistoryDataListDTO> list = weatherHistoryGetResponse.getList();
                if (CollectionUtil.isNotEmpty(list)) {
                    for (WeatherHistoryDataListDTO listDTO : list) {
                        listDTO.setCityName(cityName);
                        resultList.add(listDTO);
                    }
                }
            } catch (Exception e) {
                log.error("城市{}查询历史天气失败:", cityName, e);
            }
        }
        return resultList;
    }

    @Override
    public List<WeatherForecastListDTO> queryForecastWeather(Integer cityId) {
        List<MojiCityDO> mojiCityDOList = mojiCityMapper.getAllChinaCity();
        Map<String, MojiCityDO> cityMap = mojiCityDOList.stream().collect(Collectors.toMap(MojiCityDO::getCityCh, Function.identity()));
        WeatherMojiCommonResponse commonResponse = WeatherMojiUtil.queryForecastWeather15(cityId);
        JSONObject data = commonResponse.getData();
        if (data == null) {
            return null;
        }
        WeatherForecastResultDTO resultDTO = data.toJavaObject(WeatherForecastResultDTO.class);
        if (resultDTO == null) {
            return null;
        }
        WeatherForecastCityDataDTO cityData = resultDTO.getData();
        List<WeatherForecastListDTO> forecastList = resultDTO.getForecast();
        return forecastList;
    }

    @Override
    public List<WeatherForecastListExportDTO> queryForecastWeatherBatch(List<WeatherForecastListExportDTO> queryList) {
        // 获取所有城市
        List<MojiCityDO> mojiCityDOList = mojiCityMapper.getAllChinaCity();
        Map<String, MojiCityDO> cityMap = new HashMap<>();
        for (MojiCityDO mojiCityDO : mojiCityDOList) {
            String cityCh = mojiCityDO.getCityCh();
            cityCh = cityCh.replace("自治区", "");
            cityCh = cityCh.replace("自治县", "");
            cityCh = cityCh.replace("自治州", "");
            cityCh = cityCh.replace("地区", "");
            cityCh = cityCh.replace("林区", "");
            cityCh = cityCh.replace("市", "");
            cityCh = cityCh.replace("县", "");
            cityMap.put(cityCh, mojiCityDO);
        }
        List<WeatherForecastListExportDTO> resultList = new ArrayList<>();
        // 遍历调用
        for (WeatherForecastListExportDTO queryDTO : queryList) {
            String cityName = queryDTO.getCityName();
            MojiCityDO mojiCityDO = cityMap.get(cityName);
            if (mojiCityDO == null) {
                log.info("墨迹城市不存在：{}", cityName);
                continue;
            }
            WeatherMojiCommonResponse commonResponse = WeatherMojiUtil.queryForecastWeather15(mojiCityDO.getId());
            JSONObject data = commonResponse.getData();
            if (data == null) {
                continue;
            }
            WeatherForecastResultDTO resultDTO = data.toJavaObject(WeatherForecastResultDTO.class);
            if (resultDTO == null) {
                continue;
            }
            List<WeatherForecastListDTO> forecastList = resultDTO.getForecast();
            for (WeatherForecastListDTO listDTO : forecastList) {
                WeatherForecastListExportDTO exportDTO = new WeatherForecastListExportDTO();
                BeanUtils.copyProperties(listDTO, exportDTO);
                exportDTO.setCityName(cityName);
                resultList.add(exportDTO);
            }
        }
        return resultList;
    }

    @Override
    public List<WeatherForecastWeekExportDTO> queryAllForecastWeather() {
        // 初始化
        List<WeatherForecastWeekExportDTO> resultList = new ArrayList<>();
        // 获取所有城市
        List<MojiCityDO> mojiCityDOList = mojiCityMapper.getAllChinaCity();
        // 遍历调用
        for (MojiCityDO cityDO : mojiCityDOList) {
            // 查询组装
            WeatherForecastWeekExportDTO weekExportDTO = this.querySingleCityForecastWeather(cityDO);
            if (weekExportDTO != null) {
                resultList.add(weekExportDTO);
            }
        }
        return resultList;
    }

    private WeatherForecastWeekExportDTO querySingleCityForecastWeather(MojiCityDO cityDO) {
        // 时间初始化
        Date nowDate = new Date();
        Date nextWeekDate = DateUtil.addDays(nowDate, 7);
        Date nextTwoWeekDate = DateUtil.addDays(nowDate, 14);
        String cityName = cityDO.getCityCh();
        // 查询调用
        WeatherMojiCommonResponse commonResponse = WeatherMojiUtil.queryForecastWeather15(cityDO.getId());
        JSONObject data = commonResponse.getData();
        if (data == null) {
            log.info("墨迹城市查询天气失败:{}", cityName);
            return null;
        }
        WeatherForecastResultDTO resultDTO = data.toJavaObject(WeatherForecastResultDTO.class);
        if (resultDTO == null) {
            log.info("墨迹城市查询天气转换失败:{}", cityName);
            return null;
        }
        BigDecimal thisWeekDayTempSum = BigDecimal.ZERO;
        BigDecimal nextWeekDayTempSum = BigDecimal.ZERO;
        BigDecimal thisWeekNightTempSum = BigDecimal.ZERO;
        BigDecimal nextWeekNightTempSum = BigDecimal.ZERO;
        Map<String, Integer> thisWeekConditionMap = new HashMap<>();
        Map<String, Integer> nextWeekConditionMap = new HashMap<>();
        int thisCountDays = 0;
        int nextCountDays = 0;
        // 遍历统计
        List<WeatherForecastListDTO> forecastList = resultDTO.getForecast();
        for (WeatherForecastListDTO listDTO : forecastList) {
            Date predictDate = DateUtil.toDate(listDTO.getPredictDate() + ToolConstants.DAY_END_TIME);
            if (predictDate == null || predictDate.before(nowDate) || predictDate.after(nextTwoWeekDate)) {
                continue;
            }
            BigDecimal tempDay = new BigDecimal(listDTO.getTempDay());
            BigDecimal tempNight = new BigDecimal(listDTO.getTempNight());
            String conditionDay = listDTO.getConditionDay();
            String conditionNight = listDTO.getConditionNight();
            if (predictDate.before(nextWeekDate)) {
                // 本周
                thisWeekDayTempSum = thisWeekDayTempSum.add(tempDay);
                thisWeekNightTempSum = thisWeekNightTempSum.add(tempNight);
                if (StringUtils.isNotBlank(conditionDay)) {
                    thisWeekConditionMap.merge(conditionDay, 1, Integer::sum);
                }
                if (StringUtils.isNotBlank(conditionNight)) {
                    thisWeekConditionMap.merge(conditionNight, 1, Integer::sum);
                }
                thisCountDays++;
            } else if (predictDate.after(nextWeekDate)) {
                // 下周
                nextWeekDayTempSum = nextWeekDayTempSum.add(tempDay);
                nextWeekNightTempSum = nextWeekNightTempSum.add(tempNight);
                if (StringUtils.isNotBlank(conditionDay)) {
                    nextWeekConditionMap.merge(conditionDay, 1, Integer::sum);
                }
                if (StringUtils.isNotBlank(conditionNight)) {
                    nextWeekConditionMap.merge(conditionNight, 1, Integer::sum);
                }
                nextCountDays++;
            }
        }
        // 数据组装
        WeatherForecastWeekExportDTO weekExportDTO = new WeatherForecastWeekExportDTO();
        weekExportDTO.setCityName(cityName);
        BigDecimal thisWeekAvgDayTemp = null;
        BigDecimal thisWeekAvgNightTemp = null;
        BigDecimal nextWeekAvgDayTemp = null;
        BigDecimal nextWeekAvgNightTemp = null;
        if (thisCountDays > 0) {
            thisWeekAvgDayTemp = thisWeekDayTempSum.divide(BigDecimal.valueOf(thisCountDays), 2, RoundingMode.HALF_UP);
            thisWeekAvgNightTemp = thisWeekNightTempSum.divide(BigDecimal.valueOf(thisCountDays), 2, RoundingMode.HALF_UP);
            weekExportDTO.setThisWeekAvgDayTemp(thisWeekAvgDayTemp.toString());
            weekExportDTO.setThisWeekAvgNightTemp(thisWeekAvgNightTemp.toString());
        }
        if (nextCountDays > 0) {
            nextWeekAvgDayTemp = nextWeekDayTempSum.divide(BigDecimal.valueOf(nextCountDays), 2, RoundingMode.HALF_UP);
            nextWeekAvgNightTemp = nextWeekNightTempSum.divide(BigDecimal.valueOf(nextCountDays), 2, RoundingMode.HALF_UP);
            weekExportDTO.setNextWeekAvgDayTemp(nextWeekAvgDayTemp.toString());
            weekExportDTO.setNextWeekAvgNightTemp(nextWeekAvgNightTemp.toString());
        }
        if (thisWeekAvgDayTemp != null && nextWeekAvgDayTemp != null) {
            weekExportDTO.setDiffWeekDayTemp(nextWeekAvgDayTemp.subtract(thisWeekAvgDayTemp).toString());
        }
        if (thisWeekAvgNightTemp != null && nextWeekAvgNightTemp != null) {
            weekExportDTO.setDiffWeekNightTemp(nextWeekAvgNightTemp.subtract(thisWeekAvgNightTemp).toString());
        }
        // 取值最大的key
        thisWeekConditionMap.entrySet().stream().max(Map.Entry.comparingByValue()).
                ifPresent(entry -> weekExportDTO.setThisWeekCondition(entry.getKey()));
        nextWeekConditionMap.entrySet().stream().max(Map.Entry.comparingByValue()).
                ifPresent(entry -> weekExportDTO.setNextWeekCondition(entry.getKey()));
        return weekExportDTO;
    }

}
